/****************************************************************************
* Copyright (c) 2008, j. montgomery, ATGi                                   *
* All rights reserved.                                                      *
*                                                                           *
* Redistribution and use in source and binary forms, with or without        *
* modification, are permitted provided that the following conditions        *
* are met:                                                                  *
*                                                                           *
* - Redistributions of source code must retain the above copyright          *
*   notice, this list of conditions and the following disclaimer.           *
*                                                                           *
* - Redistributions in binary form must reproduce the above                 *
*   copyright notice, this list of conditions and the following             *
*   disclaimer in the documentation and/or other materials provided         *
*   with the distribution.                                                  *
*                                                                           *
* - Neither the name of ATGi nor the names of its contributors may          *
*   be used to endorse or promote products derived from this software       *
*   without specific prior written permission.                              *
*                                                                           *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         *
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS         *
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE            *
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,       *
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES                  *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR        *
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)        *
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,       *
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)             *
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED       *
* OF THE POSSIBILITY OF SUCH DAMAGE.                                        *
*****************************************************************************
*/
using System;
using System.IO;
using System.Text;

namespace DnSmtp.Message    
{
	/// <summary>
	/// Summary description for BinaryContent.
	/// * - would have the 'AttachmentFileName' property, but maybe called 'FileName'.
	/// * - would have a 'Body' property of type byte[] (or maybe Stream), gettable and settable.
	/// </summary>
	public class AttachmentContent : IMailContent, IDisposable

	{
		#region Fields
		private MimeType _mimeType;
		private Stream _messageBody;
		private string _attachmentFileName;
		private Encoding.IEncodingStrategy _encodingStrategy;
		private bool _disposed = false;
		#endregion Fields

		#region Properties
		public Encoding.IEncodingStrategy EncodingStrategy 
		{
			get 
			{
				return _encodingStrategy;
			}
			set 
			{
				if(value != Encoding.Base64EncodingStrategy.Instance) 
				{
					throw new ArgumentException("Attachments can only be encoded in base64");
				}
				_encodingStrategy = value;
			}
		}

		public MimeType MimeType 
		{
			get { return _mimeType; }
			set
			{
				if(value.ToString().StartsWith("multipart")) 
				{
					throw new ApplicationException("MessageContents cannot have a Multipart mime type.");
				}
				else 
				{
					_mimeType = value;
				}
			}
		}

		/// <summary>
		/// Relative file name of the attached file.
		/// </summary>
		public string FileName 
		{
			get 
			{
				return _attachmentFileName;
			}
			set 
			{
				_attachmentFileName = value;
			}
		}

		public Stream MessageBody 
		{
			get { return _messageBody; }
			set
			{
				if(value == null) 
					throw new ArgumentNullException();

				_messageBody = value;
			}
		}
		#endregion Properties

		#region Constructors
		public AttachmentContent()
		{

		}

		public AttachmentContent(MimeType mimeType, Stream mesageBody) : this()
		{
			_mimeType = mimeType;
			_messageBody = mesageBody;
		}
		#endregion Constructors

		// Use C# destructor syntax for finalization code.
		// This destructor will run only if the Dispose method 
		// does not get called.
		// It gives your base class the opportunity to finalize.
		// Do not provide destructors in types derived from this class.
		~AttachmentContent() 
		{
			Dispose(false);		
		}

		//Implement IDisposable.
		public void Dispose() 
		{
			Dispose(true);
			// Take yourself off the Finalization queue 
			// to prevent finalization code for this object
			// from executing a second time.
			GC.SuppressFinalize(this);
		}

		// Dispose(bool disposing) executes in two distinct scenarios.
		// If disposing equals true, the method has been called directly
		// or indirectly by a user's code. Managed and unmanaged resources
		// can be disposed.
		// If disposing equals false, the method has been called by the 
		// runtime from inside the finalizer and you should not reference 
		// other objects. Only unmanaged resources can be disposed.
		protected virtual void Dispose(bool disposing) 
		{
			if(disposing) 
			{
				// Free other state (managed objects).
				if(_messageBody != null) 
					_messageBody.Close();

				_messageBody = null;
				_attachmentFileName = null;
				_encodingStrategy = null;
			}

			// Free your own state (unmanaged objects).
			// Set large fields to null.


			_disposed = true;
		}

		public string BuildMessage()
		{
			if(this._disposed) 
				throw new ObjectDisposedException("AttachmentContent");

			string mailBoundry = MailMessage.GenerateMailBoundary();

			StringBuilder sb = new StringBuilder();
			sb.Append(MailMessage.CONTENT_TYPE_HEADER + _mimeType.ToString());
			
			if(_attachmentFileName == null)
			{
				// Not an attachment 
				sb.Append("; ");
                sb.Append(MailMessage.CHARSET_USASCII_HEADER);
			}
			else if(_attachmentFileName != null &&_attachmentFileName.Length > 0) 
			{
				// If attachment, include filename
				sb.Append("; ");
                sb.Append(MailMessage.FILENAME_HEADER);
                sb.Append("\"" );
                sb.Append(_attachmentFileName);
                sb.Append("\"");
			}

			sb.Append(MailMessage.CRLF);
			sb.Append("Content-Transfer-Encoding: ");
            sb.Append(_encodingStrategy.Name);
            sb.Append(MailMessage.CRLF);
			sb.Append(MailMessage.CRLF);
			sb.Append(_encodingStrategy.Encode(this.MessageBody));
			sb.Append(MailMessage.CRLF);
			return sb.ToString();
		}
	}
}
